package ai.people.platform.oss.service.impl;

import ai.people.netmon.framework.domain.oss.vo.UploadVO;
import ai.people.netmon.framework.exception.enums.FileExceptionEnum;
import ai.people.netmon.framework.exception.enums.PictureExceptionEnum;
import ai.people.netmon.framework.utils.AssertUtils;
import ai.people.netmon.utils.StringPool;
import ai.people.platform.oss.service.OssStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 本地存储服务impl
 *
 * @author yuanqinglong
 * @date 2022/5/7 10:22
 */
@RefreshScope
@Service("localStorage")
public class LocalStorageServiceImpl implements OssStorageService {
    private final Logger logger = LoggerFactory.getLogger(LocalStorageServiceImpl.class);

    /**
     * 存储目录(如果配置了存储路径使用配置的路径、如未配置默认保存当前项目同级目录/profile-picture下)
     */
    @Value("${oss.storage.fileDir:#{T(System).getProperty('user.dir') + '/profile-picture'}}")
    private String storageDirectory;

    /**
     * 上传图片
     *
     * @param multipartFile 多部分文件
     * @return {@link UploadVO}
     * @throws Exception 异常
     */
    @Override
    public UploadVO uploadPicture(MultipartFile multipartFile) throws Exception {
        String pictureName = this.createPictureName(multipartFile.getOriginalFilename());
        return getUploadVO(multipartFile, pictureName);
    }

    /**
     * 上传文件
     *
     * @param multipartFile 多部分文件
     * @return {@link UploadVO}
     * @throws Exception 异常
     */
    @Override
    public UploadVO uploadFile(MultipartFile multipartFile) throws Exception {
        String pictureName = this.createFileName(multipartFile.getOriginalFilename());
        return getUploadVO(multipartFile, pictureName);
    }

    private UploadVO getUploadVO(MultipartFile multipartFile, String pictureName) throws IOException {
        File directory = new File(storageDirectory);
        if (!directory.exists()) {
            AssertUtils.isTrue(directory.mkdir(), FileExceptionEnum.FILE_DIRECTORY_CREATION_FAILED);
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(storageDirectory + StringPool.SLASH + pictureName)) {
            fileOutputStream.write(multipartFile.getBytes());
        }
        logger.info("upload to local storage completed {}:", pictureName);
        return UploadVO.builder().build().setName(pictureName);
    }

    /**
     * 获取文件
     *
     * @param fileName            文件名称
     * @param httpServletRequest  http servlet请求
     * @param httpServletResponse 响应
     * @throws Exception 异常
     */
    @Override
    public void write(String fileName, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        File file = new File(storageDirectory, fileName);
        AssertUtils.isTrue(file.exists(), PictureExceptionEnum.IMAGE_DOES_NOT_EXIST);
        this.setPictureResponseHeaders(httpServletRequest, httpServletResponse, fileName);
        try (FileInputStream fileInputStream = new FileInputStream(file); ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream()) {
            servletOutputStream.write(fileInputStream.readAllBytes());
        }
    }

    /**
     * 写文件
     *
     * @param fileName            文件名称
     * @param httpServletRequest  http servlet请求
     * @param httpServletResponse http servlet响应
     */
    @Override
    public void writeFile(String fileName, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        File file = new File(storageDirectory, fileName);
        AssertUtils.isTrue(file.exists(), FileExceptionEnum.FILE_DOES_NOT_EXIST);
        this.setFileResponseHeaders(httpServletRequest, httpServletResponse, fileName);
        try (FileInputStream fileInputStream = new FileInputStream(file); ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream()) {
            servletOutputStream.write(fileInputStream.readAllBytes());
        }
    }

}
